<template>
  <div class="main-box">
    <TreeFilter title="表" :data="listTableInfoData" :multiple="false" :default-value="tableInfoId" @change="changeTreeFilter" />
    <el-tabs type="border-card" class="table-box demo-tabs" tab-position="top" v-model="tabVal">
      <el-tab-pane name="all">
        <template #label>
          <span class="custom-tabs-label">
            <!--            <el-icon><calendar /></el-icon>-->
            <span>全部</span>
          </span>
        </template>
      </el-tab-pane>

      <el-tab-pane v-for="item in ColumnDimensionType" :key="item.value" :label="item.label" :name="item.value" />
      <el-tab-pane label="预览" name="preview" :disabled="true">
        <template #label>
          <el-dropdown>
            <span class="el-dropdown-link"> 预览 </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item @click="tabClick('select')"> 查询页面</el-dropdown-item>
                <el-dropdown-item @click="tabClick('add')"> 新增表单</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </template>
      </el-tab-pane>

      <el-scrollbar height="100%" v-show="tabVal != 'preview'">
        <ProTable
          ref="proTable"
          highlight-current-row
          :columns="columns"
          :data="filterTableColumns"
          :tool-button="[]"
          :pagination="false"
          :init-param="tableInfoId"
          @darg-sort="sortTable"
        >
          <template #empty="scope">
            <el-button type="primary" circle size="large" :icon="Plus" @click="add(scope)" />
          </template>
          <template #operation="scope">
            <el-button type="primary" circle size="small" :icon="Plus" @click="add(scope)" />
            <el-button type="primary" circle size="small" :icon="scope.row.edit ? Check : Edit" @click="update(scope)" />
            <el-button
              type="danger"
              circle
              size="small"
              :icon="scope.row.edit ? Close : Delete"
              @click="scope.row.edit && !scope.row.newRow ? (scope.row.edit = false) : deleteTableColumn(scope)"
            />
          </template>
        </ProTable>
      </el-scrollbar>
    </el-tabs>
    <AddDataDialog :columns="tableColumns" ref="addDataDialog" :preview="true" title="预览添加表单"></AddDataDialog>
  </div>
</template>
<script setup lang="tsx" name="tableColumn">
import { computed, onMounted, reactive, ref, watch } from "vue";
import { ElMessage } from "element-plus";
import { useHandleData } from "@/hooks/useHandleData";
import {
  ColumnDimensionType,
  ColumnDimensionTypes,
  ColumnType,
  ColumnTypeEnum,
  DimensionExtraEnum,
  DimensionTypeEnum
} from "@/utils/dict";
import ProTable from "@/components/ProTable/index.vue";
import TreeFilter from "@/components/TreeFilter/index.vue";
import { ColumnProps, ProTableInstance, RenderScope } from "@/components/ProTable/interface";
import { Check, Close, Delete, Edit, Plus } from "@element-plus/icons-vue";
import { useRoute, useRouter } from "vue-router";
import { fileDetailController, tableColumnController, tableInfoController } from "@/api/modules/dwh";
import { API } from "@/api/modules/dwh/typings";
import SingleInputForm from "@/views/dwh/tableColumn/components/singleInputForm.vue";
import { generateUUID } from "@/utils";
import { isArray } from "@/utils/is";
import { useDimensionOptions } from "@/hooks/useDimensionOptions";
import AddDataDialog from "@/views/dwh/tableColumn/addDataDialog.vue";
import UploadImg from "@/components/Upload/Img.vue";

// ProTable 实例
const proTable = ref<ProTableInstance>();

const tabVal = ref<string>("all");

let route = useRoute();
let tableInfoId = ref<string>();
const router = useRouter();
const addDataDialog = ref<typeof AddDataDialog>();

const tabClick = (value: any) => {
  if (value == "select") {
    router.push(`/dwh/tableColumn/preview/${tableInfoId.value}`);
  } else if (value == "add") {
    addDataDialog.value?.show();
  }
};

let tableColumns = ref<Array<API.TableColumnVo>>([]);

const filterTableColumns = computed(() => {
  // console.log("tableInfoId.value", tableInfoId.value);
  if (!tableInfoId.value) {
    return [];
  }
  let data = tableColumns.value.filter(data => {
    return (
      data.edit ||
      ((tabVal.value == "all" ? true : data.dimensionType?.includes(tabVal.value)) &&
        (!search.val ||
          !data.id ||
          data.columnCode?.toLowerCase().includes(search.val.toLowerCase()) ||
          data.columnName?.toLowerCase().includes(search.val.toLowerCase())))
    );
  });
  // 加入新增的行
  getCurrentAddRows(Number(tableInfoId.value))?.forEach(row => {
    if (!data.includes(row)) {
      data.splice(row.index, 0, row);
    }
  });
  return data;
});

const listTableColumns = async (id: string | undefined) => {
  let result = await tableColumnController.listUsingGET({ param: Number(id) });
  result.data.forEach(data => {
    if (data.dimensionType == DimensionTypeEnum.agg) {
      data.columnCode = data.columnCode.split("_")[1];
    }
    data.dimensionType = [data.dimensionType, data.dimensionExtra];
  });
  tableColumns.value = result.data;
};

const listTableInfoData = ref<{}[]>([]);

onMounted(() => {
  listTableInfo();
});

const listTableInfo = async () => {
  let tableInfos = await tableInfoController.pageUsingPOST({ page: { pageIndex: 1, pageSize: 1000 }, query: {} });
  let result: any = {};
  if (tableInfos?.data) {
    for (const tableInfo of tableInfos.data) {
      if (tableInfo.dataSource) {
        result[tableInfo.dataSource] ?? (result[tableInfo.dataSource] = []);
        result[tableInfo.dataSource].push(tableInfo);
      }
    }
  }
  if (route.params.id != ":id") {
    tableInfoId.value = route.params.id;
  }
  for (const dataSource in result) {
    let children: Array<{}> = [];
    result[dataSource].forEach(tableInfo => {
      children.push({ id: tableInfo.id, label: tableInfo.name, subTitle: tableInfo.tableName });
      if (!tableInfoId.value) {
        tableInfoId.value = String(tableInfo.id);
      }
    });

    listTableInfoData.value.push({
      id: dataSource,
      label: dataSource,
      children: children
    });
  }
};
const addRows = ref<Array<Array<API.TableColumnVo>>>([[]]);

const removeAddRow = (newRow: API.TableColumnVo) => {
  let tableInfoId = newRow.tableInfoId!;
  getCurrentAddRows(tableInfoId).splice(getCurrentAddRows(tableInfoId).indexOf(newRow), 1);
};

const addRow = (newRow: API.TableColumnVo) => {
  let tableInfoId = newRow.tableInfoId!;
  if (!getCurrentAddRows(tableInfoId)) {
    addRows.value[tableInfoId] = [];
  }
  getCurrentAddRows(tableInfoId).push(newRow);
};

const getCurrentAddRows = (tableInfoId: number) => {
  return addRows.value[tableInfoId];
};

watch([tableInfoId], newVal => {
  listTableColumns(newVal[0]);
});

const getNewRow = (tableInfoId: number, orderNo: number, index: number, isPk: boolean): API.TableColumnVo => {
  return {
    id: generateUUID(),
    columnCode: "",
    columnName: "",
    columnOptions: "",
    columnType: ColumnTypeEnum.string,
    tableInfoId: tableInfoId,
    orderNo: orderNo,
    dimensionType: isPk
      ? [DimensionTypeEnum.dimension, DimensionExtraEnum.dimension_primary_key]
      : [DimensionTypeEnum.indicators, DimensionExtraEnum.indicators_input],
    edit: true,
    index: index,
    newRow: true
  };
};

const add = async (scope: RenderScope<API.TableColumnVo>) => {
  if (scope.row) {
    let index = filterTableColumns.value.indexOf(scope.row) + 1;

    let newRow: API.TableColumnVo = {
      id: generateUUID(),
      columnCode: "",
      columnName: "",
      columnOptions: "",
      columnType: "string",
      tableInfoId: scope.row.tableInfoId,
      orderNo: scope.row.orderNo,
      dimensionType: scope.row.dimensionType,
      dimensionExtra: "",
      edit: true,
      index: index,
      newRow: true
    };
    addRow(newRow);
  } else {
    addRow(getNewRow(Number(tableInfoId.value), 1, 0, true));
  }
};

// 表格拖拽排序
const sortTable = async ({ newIndex, oldIndex }: { newIndex?: number; oldIndex?: number }) => {
  if (newIndex === oldIndex) {
    return;
  }
  let srcTableColumnVo = filterTableColumns.value[oldIndex!];
  let targetTableColumnVo = filterTableColumns.value[newIndex!];
  if (srcTableColumnVo.newRow || targetTableColumnVo.newRow) {
    ElMessage.error("新增列需要保存后才能排序");
    return;
  }
  await tableColumnController.sortTableColumnUsingPOST({
    id: srcTableColumnVo.id as number,
    orderNo: targetTableColumnVo.orderNo!
  });
  ElMessage.success("修改列表排序成功");
};
// 更新
const update = async (scope: RenderScope<API.TableColumnVo>) => {
  if (!scope.row.edit) {
    scope.row.edit = true;
    return;
  }
  Promise.all(validateRefs.value[scope.$index].map(formRef => formRef?.validateForm()))
    .then(async res => {
      let row = scope.row;
      if (row.newRow) {
        row.id = undefined;
      }
      if (!row.edit) {
        row.edit = true;
        return;
      }
      let tableColumnVo = Object.assign({}, row);
      if (isArray(row.dimensionType)) {
        let cacheDimensionType = row.dimensionType;
        tableColumnVo.dimensionType = cacheDimensionType[0];
        tableColumnVo.dimensionExtra = cacheDimensionType[1] ?? "";
      }
      if (row.dimensionType[0] == DimensionTypeEnum.agg) {
        tableColumnVo.columnCode = row.dimensionType[1] + "@" + row.columnCode;
      }
      await tableColumnController.saveOrUpdateUsingPOST(tableColumnVo);
      listTableColumns(tableInfoId.value);
      if (row.newRow) {
        removeAddRow(row);
      }
      ElMessage.success("修改成功");
      row.edit = false;
      validateRefs[scope.$index] = [];
    })
    .catch(res => {
      console.log(res, "res");
      // ElMessage.error("必填项不能为空");
      return;
    });
};

// 更新
const deleteTableColumn = async (scope: RenderScope<API.TableColumnVo>) => {
  let row = scope.row;
  if (!row.newRow) {
    await useHandleData(
      tableColumnController.deleteUsingGET,
      { param: row.id },
      `删除 ${row.columnCode}:${row.columnName} 所选字段`
    );
    listTableColumns(tableInfoId.value);
  } else {
    removeAddRow(row);
  }
};

const search = reactive({ val: "" });

const validateRefs = ref([[]]);

const addValidateRef = (el: any, rowIndex: number) => {
  if (!validateRefs.value[rowIndex]) {
    validateRefs.value[rowIndex] = [];
  }
  validateRefs.value[rowIndex].push(el);
};

const changeDimensionType = (row: API.TableColumnVo) => {
  if (row.dimensionType[0] == DimensionTypeEnum.agg) {
    row.defaultValue = "";
    row.columnOptions = "";
  }
  if (row.columnType == ColumnTypeEnum.date) {
    row.columnOptions = "";
  }
  if (
    row.dimensionType[1] == DimensionExtraEnum.indicators_image ||
    row.dimensionType[1] == DimensionExtraEnum.indicators_file ||
    row.dimensionType[1] == DimensionExtraEnum.indicators_password
  ) {
    row.columnOptions = "";
  }
  if (row.dimensionType[1] == DimensionExtraEnum.dimension_primary_key) {
    row.columnOptions = "";
  }
};

// 表格配置项
const columns = reactive<ColumnProps<API.TableColumnVo>[]>([
  { type: "sort", label: "Sort", width: 80 },
  {
    prop: "columnCode",
    label: "code",
    render: scope =>
      scope.row.edit ? (
        <SingleInputForm
          ref={el => addValidateRef(el, scope.$index)}
          v-model={[scope.row.columnCode, "value"]}
          validateRule={{ value: [{ required: true, message: "不能为空" }] }}
        ></SingleInputForm>
      ) : (
        scope.row.columnCode ?? ""
      )
  },
  {
    prop: "columnName",
    label: "名称",
    render: scope =>
      scope.row.edit ? (
        <SingleInputForm
          ref={el => addValidateRef(el, scope.$index)}
          validateRule={{ value: [{ required: true, message: "不能为空" }] }}
          v-model={[scope.row.columnName, "value"]}
        ></SingleInputForm>
      ) : (
        scope.row.columnName ?? ""
      )
  },
  {
    prop: "columnType",
    label: "数据类型",
    // filters: ColumnType.map(columnType => {
    //   return { text: columnType.label, value: columnType.value };
    // }),
    // filterMethod: (value: string, row: API.TableColumnVo) => {
    //   return row.edit || row.columnType === value;
    // },
    render: scope =>
      scope.row.edit ? (
        <el-select
          v-model={scope.row.columnType}
          className="m-2"
          placeholder="字段类型"
          style="margin-bottom:22px"
          change={changeDimensionType(scope.row)}
        >
          {ColumnType.map(item => {
            return <el-option key={item.value} label={item.label} value={item.value}></el-option>;
          })}
        </el-select>
      ) : (
        ColumnType.find(column => column.value == (scope.row.columnType ?? ""))?.label
      )
  },
  {
    prop: "dimensionType",
    label: "类型",
    // filters: ColumnDimensionType.map(dimensionType => {
    //   return { text: dimensionType.label, value: dimensionType.value };
    // }),
    // filterMethod: (value: string, row: API.TableColumnVo) => {
    //   return row.edit || row.dimensionType === value;
    // },
    render: scope => {
      if (scope.row.edit) {
        return (
          <el-cascader
            change={changeDimensionType(scope.row)}
            options={ColumnDimensionTypes[scope.row.columnType!]}
            v-model={scope.row.dimensionType}
            style="margin-bottom:22px"
          />
        );
      }
      let columnDimensionType = ColumnDimensionTypes[scope.row.columnType!].find(
        column => column.value == (scope.row.dimensionType[0] ?? "")
      );
      let label = columnDimensionType?.label;
      if (scope.row.dimensionExtra) {
        label += "-" + columnDimensionType?.children?.find(column => column.value == scope.row.dimensionType[1])?.label;
      }
      return label;
    }
  },
  {
    prop: "defaultValue",
    label: "默认值",
    render: scope => {
      const { columnOptions } = useDimensionOptions(scope.row);
      if (scope.row.edit) {
        if (
          scope.row.dimensionType[0] == DimensionTypeEnum.indicators &&
          (scope.row.dimensionType[1] == DimensionExtraEnum.indicators_image ||
            scope.row.dimensionType[1] == DimensionExtraEnum.indicators_file)
        ) {
          return (
            <UploadImg
              v-model:image-url={scope.row.defaultValue}
              file-size={3}
              height="60"
              fileType={
                scope.row.dimensionExtra == DimensionExtraEnum.indicators_file
                  ? ["*"]
                  : ["image/jpeg", "image/jpg", "image/png", "image/gif"]
              }
              width="120"
              api={
                scope.row.dimensionExtra == DimensionExtraEnum.indicators_image
                  ? fileDetailController.uploadImageUsingPOST
                  : fileDetailController.uploadUsingPOST
              }
              v-slots={{
                tip: () => "上传内容最大为 2M"
              }}
            ></UploadImg>
          );
        }
        // 聚合字段没有默认值
        if (scope.row.dimensionType[0] == DimensionTypeEnum.agg) {
          return "";
        }
        // 没有下拉选项，返回input
        if (columnOptions.value.length < 1) {
          return (
            <SingleInputForm
              ref={el => addValidateRef(el, scope.$index)}
              v-model={[scope.row.defaultValue, "value"]}
            ></SingleInputForm>
          );
        }
        return (
          <el-select v-model={scope.row.defaultValue} className="m-2" placeholder="默认值" clearable style="margin-bottom:22px">
            {columnOptions.value.map(item => {
              return <el-option label={item.label} value={item.value} />;
            })}
          </el-select>
        );
      }
      if (!scope.row.defaultValue) {
        return "";
      }
      if (columnOptions.value.length < 1) {
        if (scope.row.defaultValue.startsWith("http")) {
          return (
            <el-link href={scope.row.defaultValue} target="_blank" type="primary">
              {scope.row.defaultValue}
            </el-link>
          );
        } else {
          return scope.row.defaultValue;
        }
      }
      return columnOptions.value?.find(option => option.value == scope.row.defaultValue)?.label ?? "";
    }
  },
  {
    prop: "columnOptions",
    label: "枚举值",
    render: scope =>
      scope.row.edit ? (
        (scope.row.dimensionType[0] == DimensionTypeEnum.indicators &&
          (scope.row.dimensionType[1] == DimensionExtraEnum.indicators_image ||
            scope.row.dimensionType[1] == DimensionExtraEnum.indicators_file)) ||
        scope.row.dimensionType[0] == DimensionTypeEnum.agg ||
        scope.row.columnType == ColumnTypeEnum.date ? (
          ""
        ) : (
          <SingleInputForm
            ref={el => addValidateRef(el, scope.$index)}
            validateRule={{
              value: [
                {
                  pattern: /^(([\u4E00-\u9FA5A-Za-z0-9]+):([\u4E00-\u9FA5A-Za-z0-9]+)(,?))+$/,
                  message: "格式要求: key:value,key:value"
                }
              ]
            }}
            placeholder="格式要求：key:value,key:value"
            v-model={[scope.row.columnOptions, "value"]}
          ></SingleInputForm>
        )
      ) : (
        <el-tooltip
          placement="top"
          v-slots={{
            content: () => {
              return (
                <>
                  {scope.row.columnOptions?.split(",").map(item => {
                    return (
                      <>
                        {item}
                        <br />
                      </>
                    );
                  })}
                </>
              );
            }
          }}
        >
          {scope.row.columnOptions ?? ""}
        </el-tooltip>
      )
  },
  {
    prop: "operation",
    label: "操作",
    fixed: "right",
    // width: 150,
    headerRender: scope => {
      return <el-input v-model={search.val} size="default" placeholder="搜索" />;
    }
  }
]);

// 默认 treeFilter 参数
const changeTreeFilter = (val: string) => {
  tableInfoId.value = val;
};
</script>
<style scoped>
.demo-tabs > .el-tabs__content {
  padding: 32px;
  font-size: 32px;
  font-weight: 600;
  color: #6b778c;
}

.demo-tabs .custom-tabs-label .el-icon {
  vertical-align: middle;
}

.demo-tabs .custom-tabs-label span {
  margin-left: 4px;
  vertical-align: middle;
}
</style>
